/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package org.mm.proxycache.http;

import com.google.common.base.Preconditions;

/**
 * 
 * @author The Apache MINA Project (dev@mina.apache.org)
 * @version $Id: HttpResponseStatus.java 69 2008-02-11 09:30:27Z matteo.merli $
 */
public class HttpResponseStatus
{
    
    private static final int MIN_ID = 100;
    
    private static final int MAX_ID = 599;
    
    private static final HttpResponseStatus[] RESPONSE_TABLE = new HttpResponseStatus[MAX_ID + 1];
    
    // Informational status codes
    
    public static final HttpResponseStatus Continue = new HttpResponseStatus( 100, "Continue",
            true, false );
    
    public static final HttpResponseStatus SwitchingProtocols = new HttpResponseStatus( 101,
            "Switching Protocols", true, false );
    
    // Successful status codes
    
    public static final HttpResponseStatus OK = new HttpResponseStatus( 200, "OK", true, false );
    
    public static final HttpResponseStatus Created = new HttpResponseStatus( 201, "Created", true,
            false );
    
    public static final HttpResponseStatus Accepted = new HttpResponseStatus( 202, "Accepted",
            true, false );
    
    public static final HttpResponseStatus NonAuthoritativeInformation = new HttpResponseStatus(
            203, "Non-Authoritative Information", true, false );
    
    public static final HttpResponseStatus NoContent = new HttpResponseStatus( 204, "No Content",
            false, false );
    
    public static final HttpResponseStatus ResetContent = new HttpResponseStatus( 205,
            "Reset Content", false, false );
    
    public static final HttpResponseStatus PartialContent = new HttpResponseStatus( 206,
            "Partial Content", true, false );
    
    // Redirection status codes
    
    public static final HttpResponseStatus MultipleChoices = new HttpResponseStatus( 300,
            "Multiple Choices", true, false );
    
    public static final HttpResponseStatus MovedPermanently = new HttpResponseStatus( 301,
            "Moved Permanently", true, false );
    
    public static final HttpResponseStatus Found = new HttpResponseStatus( 302, "Found", true,
            false );
    
    public static final HttpResponseStatus SeeOther = new HttpResponseStatus( 303, "See Other",
            true, false );
    
    public static final HttpResponseStatus NotModified = new HttpResponseStatus( 304,
            "Not Modified", false, false );
    
    public static final HttpResponseStatus UseProxy = new HttpResponseStatus( 305, "Use Proxy",
            true, false );
    
    public static final HttpResponseStatus TemporaryRedirect = new HttpResponseStatus( 307,
            "Temporary Redirect", true, false );
    
    // Client error codes
    
    public static final HttpResponseStatus BadRequest = new HttpResponseStatus( 400, "Bad Request",
            true, true );
    
    public static final HttpResponseStatus Unauthorized = new HttpResponseStatus( 401,
            "Unauthorized", true, false );
    
    public static final HttpResponseStatus PaymentRequired = new HttpResponseStatus( 402,
            "Payment Required", true, false );
    
    public static final HttpResponseStatus Forbidden = new HttpResponseStatus( 403, "Forbidden",
            true, false );
    
    public static final HttpResponseStatus NotFound = new HttpResponseStatus( 404, "Not Found",
            true, false );
    
    public static final HttpResponseStatus MethodNotAllowed = new HttpResponseStatus( 405,
            "Method Not Allowed", true, false );
    
    public static final HttpResponseStatus NotAcceptable = new HttpResponseStatus( 406,
            "Not Acceptable", true, false );
    
    public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED = new HttpResponseStatus(
            407, "Proxy Authentication Required", true, false );
    
    public static final HttpResponseStatus RequestTimeout = new HttpResponseStatus( 408,
            "Request Time-out", true, true );
    
    public static final HttpResponseStatus Conflict = new HttpResponseStatus( 409, "Conflict",
            true, false );
    
    public static final HttpResponseStatus Gone = new HttpResponseStatus( 410, "Gone", true, false );
    
    public static final HttpResponseStatus LengthRequired = new HttpResponseStatus( 411,
            "Length Required", true, true );
    
    public static final HttpResponseStatus PreconditionFailed = new HttpResponseStatus( 412,
            "Precondition Failed", true, false );
    
    public static final HttpResponseStatus RequestEntityTooLarge = new HttpResponseStatus( 413,
            "Request Entity Too Large", true, true );
    
    public static final HttpResponseStatus RequestUriTooLong = new HttpResponseStatus( 414,
            "Request-URI Too Large", true, true );
    
    public static final HttpResponseStatus UnsupportedMediaType = new HttpResponseStatus( 415,
            "Unsupported Media Type", true, false );
    
    public static final HttpResponseStatus RequestRangeNotSatisfuable = new HttpResponseStatus(
            416, "Requested range not satisfiable", true, false );
    
    public static final HttpResponseStatus ExpectationFailed = new HttpResponseStatus( 417,
            "Expectation Failed", true, false );
    
    // Server error codes
    
    public static final HttpResponseStatus InternalServerError = new HttpResponseStatus( 500,
            "Internal Server Error", true, true );
    
    public static final HttpResponseStatus NotImplemented = new HttpResponseStatus( 501,
            "Not Implemented", true, true );
    
    public static final HttpResponseStatus BadGateway = new HttpResponseStatus( 502, "Bad Gateway",
            true, false );
    
    public static final HttpResponseStatus ServiceUnavailable = new HttpResponseStatus( 503,
            "Service Unavailable", true, true );
    
    public static final HttpResponseStatus GatewayTimeout = new HttpResponseStatus( 504,
            "Gateway Time-out", true, false );
    
    public static final HttpResponseStatus HttpVersionNotSupported = new HttpResponseStatus( 505,
            "HTTP Version not supported", true, false );
    
    private final int code;
    
    private final transient boolean allowsMessageBody;
    
    private final transient boolean forcesConnectionClosure;
    
    private final transient String description;
    
    /**
     * @return <code>true</code> iff a message body may be transmitted in a
     *         response containing this response status
     */
    public boolean allowsMessageBody()
    {
        return allowsMessageBody;
    }
    
    /**
     * @return <code>true</code> iff a connection which would normally be kept
     *         alive should be closed as a result of this response
     */
    public boolean forcesConnectionClosure()
    {
        return forcesConnectionClosure;
    }
    
    /**
     * @return The response code of this status
     */
    public int getCode()
    {
        return code;
    }
    
    /**
     * @return A description of this status
     */
    public String getDescription()
    {
        return description;
    }
    
    /**
     * A string description of this status
     */
    @Override
    public String toString()
    {
        return code + " " + description;
    }
    
    /**
     * Returns the <code>ResponseStatus</code> with the specified status id.
     * If no status exists with the specified id, a new status is created and
     * registered based on the category applicable to the id:<br/> <table
     * border="1">
     * <tr>
     * <td>100 - 199</td>
     * <td>Informational</td>
     * </tr>
     * <tr>
     * <td>200 - 299</td>
     * <td>Successful</td>
     * </tr>
     * <tr>
     * <td>300 - 399</td>
     * <td>Redirection</td>
     * </tr>
     * <tr>
     * <td>400 - 499</td>
     * <td>Client Error</td>
     * </tr>
     * <tr>
     * <td>500 - 599</td>
     * <td>Server Error</td>
     * </tr>
     * <table>.
     * 
     * @param id
     *            The id of the desired response status
     * @return The <code>ResponseStatus</code>
     * @throws IllegalStateException
     *             If the specified id is invalid
     */
    public static HttpResponseStatus forId( int id )
    {
        Preconditions.checkArgument( !(id < MIN_ID || id > MAX_ID), "Illegal response id:  %d", id );
        
        HttpResponseStatus status = RESPONSE_TABLE[id];
        Preconditions.checkNotNull( status );
        return status;
    }
    
    private HttpResponseStatus( int code, String description, boolean allowsMessageBody,
            boolean forcesConnectionClosure )
    {
        RESPONSE_TABLE[code] = this;
        this.code = code;
        this.description = description;
        this.allowsMessageBody = allowsMessageBody;
        this.forcesConnectionClosure = forcesConnectionClosure;
    }
    
}
